package pl.edu.romanow.model

import net.liftweb.json.JsonDSL._
import scala.collection.JavaConversions._
import GraphHelper._
import Database._
import com.tinkerpop.blueprints.pgm.{Edge, Vertex}
import net.liftweb.json.{JsonAST, Printer}
import net.liftweb.json.JsonAST.{JArray, JObject}
import net.liftweb.common.Loggable
import com.tinkerpop.gremlin.scala.GremlinScalaPipeline
import net.liftweb.http.SHtml
import net.liftweb.http.js.JsCmds.{Function, Script}
import net.liftweb.http.js.JsCmds
import pl.edu.romanow.util.HTMLUtil
import net.liftweb.http.js.JE.{JsRaw, Str}
import pl.edu.romanow.snippet.RightMenu

/**
 * Created by IntelliJ IDEA.
 * User: jar
 * Date: 18.04.12
 * Time: 14:13
 * To change this template use File | Settings | File Templates.
 */

object GraphVisualisationUtil extends Loggable {

  def standard_node(color: String = "83548B") = ("data" -> (
    ("$color" -> ("#" + color)) ~
      ("$type" -> "circle") ~
      ("$dim" -> 10)
    ))

  val standard_edge = ("data" -> (
    "$color" -> "#557EAA"
    ))


  def displayNode(v: Vertex, edgesPerVertex: Vertex => GremlinScalaPipeline[_, Edge], allV: Seq[Vertex]): JObject = {

    displayVertex(v, edgesPerVertex(v).filter((e: Edge) =>
      allV.contains(e.getInVertex) &&
        allV.contains(e.getOutVertex)).toList)
  }


  def displayVertex(v: Vertex, edges: Seq[Edge]): JObject = {
    ("name" -> (v \ "name")) ~
      ("id" -> v.getId.toString) ~
      standard_node(v.\?("cluster").openOr("83548B")) ~
      ("adjacencies" -> JArray(edges.map {
        to => standard_edge ~
          ("nodeTo" -> to.getOutVertex.getId.toString) ~
          ("nodeFrom" -> to.getInVertex.getId.toString)
      }.toList))
  }


  def displayGraph(
                    vertex: Vertex => GremlinScalaPipeline[_, Vertex],
                    edgesPerVertex: Vertex => GremlinScalaPipeline[_, Edge])
                  (startPoint: Vertex, addStartPoint: Boolean = false): String = {
    val allVertex = vertex(startPoint).toList
    if (addStartPoint)
      allVertex.add(startPoint)

    val text = Printer.pretty(JsonAST.render(JArray(allVertex.map {
      GraphVisualisationUtil.displayNode(_, edgesPerVertex, allVertex)
    }.toList)))

    //logger.info("Json data: \n" + text)

    text
  }


  def displayGraph(edges: Seq[Edge]): (String, Boolean) = {

    val vertex = scala.collection.mutable.HashMap[AnyRef, (Vertex, Set[Edge])]()

    var toMuch = false;

    println("Got %d edges".format(edges.size))

    edges.foreach {
      e => val in = e.getInVertex
      val out = e.getOutVertex
      if (!toMuch) {
        vertex += ((in.getId, vertex.get(in.getId) match {
          case Some(el) => (el._1, (el._2 + e))
          case _ => (in, Set(e))
        }))
        vertex += ((out.getId, vertex.get(out.getId) match {
          case Some(sth) => sth
          case _ => (out, Set[Edge]())
        }))
      } else {
        vertex.get(in.getId) match {
          case Some(el) if vertex.contains(out.getId) =>
            vertex.+=((in.getId, (el._1, el._2 + e)))
          case _ => ""
        }
      }
      toMuch = vertex.size > 400;
    }

    (Printer.pretty(JsonAST.render(JArray(vertex.map {
      el => displayVertex(el._2._1, el._2._2.toSeq)
    }.toList))), toMuch)
  }


  val displayFriends =
    displayGraph(G(_).out("friends"), G(_).inE("friends"))(_: Vertex, true)


  def nodeToolTipFunction() =
    JsCmds.Run(
      """function nodeToolTip(node){
           return  "<div class=\"tip-title\">" + node.name + "</div>"
            }""")

  def onNodeClickFunction() =
    HTMLUtil.ajaxJsFunction(name = "onNodeClick",
      params = "node" :: Nil,
      body = st => RightMenu.showUser(st.head),
      formatter = _ => JsRaw("node.id")
    )


}
